<?php

namespace Yousheng\Ku\Generators;

use Yousheng\Ku\Contracts\GeneratorInterface;
use Yousheng\Ku\Ku;
use Yousheng\Ku\Mergers\MergerContainer;
use Yousheng\Ku\Support\Path;
use Yousheng\Ku\Table;
use Illuminate\Support\Facades\File;

/**
 * Generator for `dist/database/migrations/*.php`.
 */
final class MigrationGenerator implements GeneratorInterface
{
    /**
     * @var string Stub string from the stubs folder file.
     */
    private string $stub;

    /**
     * The left padding for the body of the generated.
     */
    public const INTENT = '            ';





    /**
     * Engines for MergerContainer.
     *
     * @var ?array<\Yousheng\Ku\Mergers\Merger>
     */
    private ?array $mergerEngines = null;

    private function __construct(
        private Table $table,
        private ?string $namespace = null,
        private ?string $destination = null
    ) {
        if (is_null($destination)) {
            // $this->destination = Path::migration();
            $this->destination = database_path('migrations');
        }

        // $this->stub = File::system()->read(Path::stub().DIRECTORY_SEPARATOR.'Migration.stub');
        $this->stub = File::get(Ku::stubPath('Migration'));
    }

    /**
     * 获取向上迁移的代码。
     *
     * @param bool $force 是否强制覆盖已有文件
     * @param bool $merge 是否仅返回合并后的代码而不保存文件
     * @param string|null $databaseName 数据库名称
     * @return string|null 向上迁移的代码，如果出现异常或无内容则返回 null
     */
    public function getUp(bool $force = false, bool $merge = false, string|null $databaseName = null): ?string
    {
        $fields = '';

        $currentTable = $this->table->getName();

        $columns = $this->table->getColumns();

        foreach ($columns as $column) {

            $fields .= self::INTENT . $column->migration() . PHP_EOL;
        }

        $foreigns = $this->table->getForeignKeys();
     
        foreach ($foreigns as $foreign) {
            $fields .= self::INTENT . $foreign->migration() . PHP_EOL;
        }

        $indexes = $this->table->getIndexes();
     
        foreach ($indexes as $index) {
            $fields .= PHP_EOL.self::INTENT . $index->migration();
        }

        // $indexes = $this->table->getIndex();

        return $fields;
    }

    /**
     * {@inheritDoc}
     */
    public function run(bool $force = false,  string|null $databaseName = null): void
    {
        $fields = $this->getUp($force, false, $databaseName);
        $fields = preg_replace('/\n$/', '', $fields); // 删除换行符

        $seederClass = str_replace(
            ['{table}', '{fields}'],
            [$this->table, $fields],
            $this->stub
        );

        if (! is_null($this->mergerEngines)) {
            $seederClass = MergerContainer::from(body: $seederClass)
                ->engines($this->mergerEngines)
                ->operating()
                ->verbose();
        }

        File::put(
            $this->destination . DIRECTORY_SEPARATOR . $this->table->migration(),
            $seederClass,
            $force
        );
    }

    /**
     * Set merger engines.
     *
     * @param  array<\Yousheng\Ku\Mergers\Merger>  $engines  An array of merger engines.
     * @return static The method returns the current instance that enables methods chaining.
     */
    public function merging(array $engines): static
    {
        $this->mergerEngines = $engines;

        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public static function make(
        Table $table,
        ?string $namespace = null,
        ?string $destination = null
    ): static {
        return new self($table, $namespace, $destination);
    }
}
